package com.wu.flandre.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wu.flandre.component.GlobalConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import java.net.URI;
import java.util.Map;

/**
 * HttpRequestUtil Http请求工具<br/>
 *
 * @author 50816 <br/>
 * @date 2019/12/14 14:25 <br/>
 */
@Slf4j
public class HttpRequestUtil {

    private static volatile HttpRequestUtil instance = null;

    private HttpRequestUtil() {
    }

    public static HttpRequestUtil getInstance() {
        synchronized (HttpRequestUtil.class) {
            if (instance == null) {
                instance = new HttpRequestUtil();
            }
        }
        return instance;
    }

    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 发送HTTP GET请求,返回字符串
     *
     * @param url 请求URL
     * @return 字符串
     */
    public String doGet2String(String url) {
        return (String) this.commonRequest(url, GlobalConstant.DO_GET, null, null);
    }

    /**
     * 发送HTTP GET请求返回实体对象
     *
     * @param url   请求URL
     * @param clazz 实体类class
     * @param <T>   实体类类型
     */
    public <T> T doGet2Entity(String url, Class<T> clazz) {
        return (T) this.commonRequest(url, GlobalConstant.DO_GET, null, clazz);
    }

    /**
     * 发送HTTP POST请求返回字符串
     *
     * @param url    URL
     * @param params 请求参数
     */
    public String doPost2String(String url, Map<String, String> params) {
        return (String) this.commonRequest(url, GlobalConstant.DO_POST, params, null);
    }

    /**
     * HTTP POST请求返回实体类
     *
     * @param url    URL
     * @param params 请求参数
     * @param clazz  实体类
     * @param <T>    类型
     * @return
     */
    public <T> T doPost2Entity(String url, Map<String, String> params, Class<T> clazz) {
        return (T) this.commonRequest(url, GlobalConstant.DO_POST, params, clazz);
    }

    /**
     * HTTP PUT 请求返回字符串
     *
     * @param url    URL
     * @param params 请求参数
     * @return
     */
    public String doPut2String(String url, Map<String, String> params) {
        return (String) this.commonRequest(url, GlobalConstant.DO_PUT, params, null);
    }

    /**
     * HTTP PUT 请求返回实体类
     *
     * @param url    URL
     * @param params 请求参数
     * @param clazz  实体类
     * @param <T>    类型
     * @return
     */
    public <T> T doPut2Entity(String url, Map<String, String> params, Class<T> clazz) {
        return (T) this.commonRequest(url, GlobalConstant.DO_PUT, params, clazz);
    }

    /**
     * HTTP DELETE 请求返回字符串
     *
     * @param url    URL
     * @param params 请求参数
     * @return
     */
    public String doDelete2String(String url, Map<String, String> params) {
        return (String) this.commonRequest(url, GlobalConstant.DO_DELETE, params, null);
    }

    /**
     * HTTP DELETE 请求返回实体类
     *
     * @param url    URL
     * @param params 请求参数
     * @param clazz  实体类
     * @param <T>    类型
     * @return
     */
    public <T> T doDelete2Entity(String url, Map<String, String> params, Class<T> clazz) {
        return (T) this.commonRequest(url, GlobalConstant.DO_DELETE, params, clazz);
    }

    /**
     * 公共请求方法
     *
     * @param url    URL
     * @param method 请求方法
     * @param params 请求参数
     * @param clazz  实体类
     * @return
     */
    private Object commonRequest(String url, String method, Map<String, String> params, Class<?> clazz) {
        Object result = null;
        HttpClient httpClient = HttpClientBuilder.create().build();
        HttpResponse response = null;
        HttpGet get = null;
        HttpPost post = null;
        HttpPut put = null;
        HttpDelete delete = null;
        try {
            URIBuilder uriBuilder = new URIBuilder(url);
            if (null != params && !params.isEmpty()) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    uriBuilder.addParameter(entry.getKey(), entry.getValue());
                }
            }
            URI uri = uriBuilder.build();
            switch (method) {
                case GlobalConstant.DO_GET:
                    get = new HttpGet(uri);
                    response = httpClient.execute(get);
                    break;
                case GlobalConstant.DO_POST:
                    post = new HttpPost(uri);
                    response = httpClient.execute(post);
                    break;
                case GlobalConstant.DO_PUT:
                    put = new HttpPut();
                    response = httpClient.execute(put);
                    break;
                case GlobalConstant.DO_DELETE:
                    delete = new HttpDelete();
                    response = httpClient.execute(delete);
                    break;
                default:
                    log.error("不正确的请求方法,请求中止");
                    return null;
            }
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                if (null == clazz) {
                    result = EntityUtils.toString(response.getEntity());
                } else {
                    String content = EntityUtils.toString(response.getEntity());
                    result = objectMapper.readValue(content, clazz);
                }
            }
        } catch (Exception e) {
            log.error("请求URL时发生异常,e:" + e.getMessage() + ",请求地址:" + url);
        } finally {
            //关闭所有连接
            if (null != get) {
                get.releaseConnection();
            }
            if (null != post) {
                post.releaseConnection();
            }
            if (null != put) {
                put.releaseConnection();
            }
            if (null != delete) {
                delete.releaseConnection();
            }
        }
        return result;
    }

}